package com.km.team.phsystem.web.controller;

import com.alibaba.fastjson.JSON;
import com.km.team.phsystem.beans.vo.ResponseData;
import com.km.team.phsystem.common.enums.ResultEnum;
import com.km.team.phsystem.common.exception.SystemErrorException;
import com.km.team.phsystem.web.config.XfConfig;
import com.km.team.phsystem.web.controller.base.BaseController;
import com.km.team.phsystem.web.support.PoolingSimpleHttpClient;
import com.km.team.phsystem.web.utils.Base64Utils;
import com.km.team.phsystem.web.utils.CalendarUtils;
import com.km.team.phsystem.web.utils.ResponseDataUtil;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.entity.ContentType;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * Author: jiangjun
 * Date: 2018/10/18
 * Time: 下午11:03
 * Description: 语音合成
 */
@RestController
@RequestMapping("/xf")
public class SpeechController extends BaseController<SpeechController> {

    @Autowired
    private XfConfig xfConfig;

    @Autowired
    private PoolingSimpleHttpClient httpClient;

    /**
     * 语音合成
     * @param text
     * @throws Exception
     */
    @GetMapping("/tts/{text}")
    public ResponseData tts(@PathVariable("text") String text,
                            HttpServletResponse httpResponse) throws Exception{
        long startTime = System.currentTimeMillis();
        text = text.replace(" ", "");
        HttpResponse response = httpClient.post(xfConfig.getTts(), genParams(text), genHeaders());
        long endTime = System.currentTimeMillis();
        logger.info("结束http get请求!用时：{} ms", (endTime - startTime));
        OutputStream outputStream = null;
        String fileName = null;
        try {
            // http请求成功
            HttpEntity entity = response.getEntity();
            ContentType contentType = ContentType.get(entity);
            if(contentType.getMimeType().equals(ContentType.TEXT_PLAIN.getMimeType())){
                String result = EntityUtils.toString(entity, "utf-8");
                logger.error("调用异常，返回结果：{}", result);
                return ResponseDataUtil.buildError(ResultEnum.ERROR);
            }
            // 创建文件夹
            String dir = xfConfig.getSaveDir() + genSaveDir();
            File saveDir = new File(dir);
            if(!saveDir.exists()){
                saveDir.mkdirs();
            }
            InputStream inputStream = entity.getContent();
            //OutputStream outputStream = httpResponse.getOutputStream();
            fileName = dir + getCuurentTimeStr() + ".mp3";
            File mp3 = new File(fileName);
            outputStream = new FileOutputStream(mp3);
            byte[] bytes = new byte[1024];
            int len = -1;
            while ((len=inputStream.read(bytes))!= -1){
                outputStream.write(bytes,0,len);
            }
        } catch (Exception e) {
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());//会自动释放连接
                } catch (IOException e1) {
                    logger.error("关闭response异常！异常信息：" + e);
                }
            }
            String extraMsg = "http请求异常！response.getEntity序列化异常！";
            throw new SystemErrorException(ResultEnum.ERROR.getCode(), ResultEnum.ERROR.getMessage(),
                    extraMsg, e);
        } finally {
            if (response != null) {
                try {
                    EntityUtils.consume(response.getEntity());//会自动释放连接
                } catch (IOException e) {
                    logger.error("关闭response异常！异常信息：" + e);
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    logger.error("关闭response异常！异常信息：" + e);
                }
            }
        }
        return ResponseDataUtil.buildSuccess(fileName.replace(xfConfig.saveDir, ""));
    }


    private String getCuurentTimeStr(){
        LocalDateTime now = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddhhmmss");
        return now.format(formatter);
    }

    /**
     * 封装请求体
     * @param text
     * @return
     */
    private List<NameValuePair> genParams(String text){
        NameValuePair textParam = new BasicNameValuePair("text", text);
        List<NameValuePair> params = new ArrayList<>();
        params.add(textParam);
        return params;
    }

    /**
     * 封装请求头
     * @return
     * @throws Exception
     */
    private List<Header> genHeaders() throws Exception{
        List<Header> headers = new ArrayList<>();

        Header appid = new BasicHeader("X-Appid", xfConfig.getAppId());
        String curTimeStr = CalendarUtils.getUTCTimeStr();
        Header curTime = new BasicHeader("X-CurTime", curTimeStr);

        Map<String,String> map = new HashMap<String,String>();
        map.put("auf", xfConfig.getAuf());
        map.put("aue", xfConfig.getAue());
        map.put("voice_name", xfConfig.getVoiceName());
        map.put("speed", xfConfig.getSpeed());
        String json = JSON.toJSONString(map);
        String encodedText = Base64Utils.encode(json);
        Header param = new BasicHeader("X-Param", encodedText);

        String md5Raw = xfConfig.getApiKey()+ curTimeStr + encodedText;
        String checkSumStr = DigestUtils.md5DigestAsHex(md5Raw.getBytes());
        Header checkSum = new BasicHeader("X-CheckSum", checkSumStr);

        headers.add(appid);
        headers.add(curTime);
        headers.add(param);
        headers.add(checkSum);
        return headers;
    }

    /**
     * 构造保存目录
     * @return
     */
    private String genSaveDir(){
        LocalDate now = LocalDate.now();
        int year = now.getYear();
        int month = now.getMonth().getValue() + 1;
        int day = now.getDayOfMonth();
        return year + File.separator + month + File.separator + day + File.separator;
    }
}
